package org.bing.engine.common.remoting.hessian;

import java.io.InputStream;
import java.net.URL;

import org.bing.adapter.com.caucho.hessian.client.HessianConnection;
import org.bing.adapter.com.caucho.hessian.client.HessianProxy;
import org.bing.adapter.com.caucho.hessian.client.HessianRuntimeException;
import org.bing.adapter.com.caucho.hessian.io.AbstractHessianInput;
import org.bing.adapter.com.caucho.hessian.io.HessianProtocolException;
import org.bing.engine.common.remoting.RemotingInvoker;
import org.bing.logging.Logger;
import org.bing.logging.LoggerFactory;

public class HessianInvoker extends HessianProxy implements RemotingInvoker {
    private static final org.bing.adapter.com.caucho.hessian.client.HessianProxyFactory factory = new org.bing.adapter.com.caucho.hessian.client.HessianProxyFactory();
    private static final long serialVersionUID = 1978L;
    private static final Logger logger = LoggerFactory.getLogger(HessianInvoker.class);

    protected HessianInvoker(URL url, String clz) {
        super(url, factory);
    }

    public Object invoke(String method, Object[] args) {
        // TODO filter some method:equals,hashCode,getHessianType,getHessianURL,toString
        String mangleName = method;
        InputStream is = null;
        HessianConnection conn = null;
        try {
            conn = sendRequest(mangleName, args);
            is = conn.getInputStream();
            AbstractHessianInput in;
            int code = is.read();
            if (code == 'H') {
                @SuppressWarnings("unused")
                int major = is.read();
                @SuppressWarnings("unused")
                int minor = is.read();
                in = _factory.getHessian2Input(is);
                Object value = in.readReply(null);
                return value;
            } else
                throw new HessianProtocolException("'" + (char) code + "' is an unknown code");
        } catch (HessianProtocolException e) {
            throw new HessianRuntimeException(e);
        } catch (Throwable t) {
            throw new RuntimeException(t);
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                logger.warn("Fail to close hessian stream !", e);
            } 
            try {
                if (conn != null) {
                    conn.destroy();
                }
            } catch (Exception e) {
                logger.warn("Fail to close hessian connection !", e);
            }
        }
    }
}
